package com.zouxw.utils.json.utils;

import java.lang.management.ManagementFactory;
import java.lang.management.MemoryMXBean;
import java.lang.management.MemoryUsage;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;

/**
 * 内存管理工具类
 * 提供内存监控、垃圾回收和内存优化功能
 * 
 * @author zouxw
 * @version 1.0
 */
public class MemoryManager {
    
    // ==================== 配置常量 ====================
    /** 内存警告阈值（百分比） */
    private static final double MEMORY_WARNING_THRESHOLD = 80.0;
    
    /** 内存危险阈值（百分比） */
    private static final double MEMORY_DANGER_THRESHOLD = 90.0;
    
    /** 内存监控间隔（秒） */
    private static final int MONITOR_INTERVAL = 5;
    
    // ==================== 实例变量 ====================
    /** 内存管理Bean */
    private final MemoryMXBean memoryBean;
    
    /** 定时任务执行器 */
    private ScheduledExecutorService scheduler;
    
    /** 内存警告回调 */
    private Consumer<MemoryStatus> warningCallback;
    
    /** 内存危险回调 */
    private Consumer<MemoryStatus> dangerCallback;
    
    // ==================== 构造函数 ====================
    
    /**
     * 构造函数
     */
    public MemoryManager() {
        this.memoryBean = ManagementFactory.getMemoryMXBean();
    }
    
    // ==================== 公共方法 ====================
    
    /**
     * 开始内存监控
     * 
     * @param warningCallback 内存警告回调
     * @param dangerCallback 内存危险回调
     */
    public void startMonitoring(Consumer<MemoryStatus> warningCallback, Consumer<MemoryStatus> dangerCallback) {
        this.warningCallback = warningCallback;
        this.dangerCallback = dangerCallback;
        
        if (scheduler == null || scheduler.isShutdown()) {
            scheduler = Executors.newSingleThreadScheduledExecutor();
            scheduler.scheduleAtFixedRate(this::checkMemoryUsage, 0, MONITOR_INTERVAL, TimeUnit.SECONDS);
        }
    }
    
    /**
     * 停止内存监控
     */
    public void stopMonitoring() {
        if (scheduler != null && !scheduler.isShutdown()) {
            scheduler.shutdown();
            try {
                if (!scheduler.awaitTermination(1, TimeUnit.SECONDS)) {
                    scheduler.shutdownNow();
                }
            } catch (InterruptedException e) {
                scheduler.shutdownNow();
                Thread.currentThread().interrupt();
            }
        }
    }
    
    /**
     * 获取当前内存状态
     * 
     * @return 内存状态
     */
    public MemoryStatus getMemoryStatus() {
        MemoryUsage heapUsage = memoryBean.getHeapMemoryUsage();
        MemoryUsage nonHeapUsage = memoryBean.getNonHeapMemoryUsage();
        
        return new MemoryStatus(heapUsage, nonHeapUsage);
    }
    
    /**
     * 执行垃圾回收
     */
    public void performGarbageCollection() {
        System.gc();
    }
    
    /**
     * 获取内存使用率
     * 
     * @return 内存使用率（0-100）
     */
    public double getMemoryUsagePercentage() {
        MemoryStatus status = getMemoryStatus();
        return status.getHeapUsagePercentage();
    }
    
    /**
     * 检查是否需要垃圾回收
     * 
     * @return 是否需要垃圾回收
     */
    public boolean shouldPerformGC() {
        return getMemoryUsagePercentage() > MEMORY_WARNING_THRESHOLD;
    }
    
    /**
     * 获取内存统计信息
     * 
     * @return 内存统计信息
     */
    public MemoryStatistics getMemoryStatistics() {
        MemoryStatus status = getMemoryStatus();
        return new MemoryStatistics(status);
    }
    
    // ==================== 私有方法 ====================
    
    /**
     * 检查内存使用情况
     */
    private void checkMemoryUsage() {
        MemoryStatus status = getMemoryStatus();
        double usagePercentage = status.getHeapUsagePercentage();
        
        if (usagePercentage >= MEMORY_DANGER_THRESHOLD && dangerCallback != null) {
            dangerCallback.accept(status);
        } else if (usagePercentage >= MEMORY_WARNING_THRESHOLD && warningCallback != null) {
            warningCallback.accept(status);
        }
    }
    
    // ==================== 内部类 ====================
    
    /**
     * 内存状态类
     */
    public static class MemoryStatus {
        private final MemoryUsage heapUsage;
        private final MemoryUsage nonHeapUsage;
        
        public MemoryStatus(MemoryUsage heapUsage, MemoryUsage nonHeapUsage) {
            this.heapUsage = heapUsage;
            this.nonHeapUsage = nonHeapUsage;
        }
        
        public MemoryUsage getHeapUsage() { return heapUsage; }
        public MemoryUsage getNonHeapUsage() { return nonHeapUsage; }
        
        public long getUsedMemory() { return heapUsage.getUsed(); }
        public long getMaxMemory() { return heapUsage.getMax(); }
        public long getFreeMemory() { return heapUsage.getMax() - heapUsage.getUsed(); }
        
        public double getHeapUsagePercentage() {
            if (heapUsage.getMax() <= 0) return 0;
            return (double) heapUsage.getUsed() / heapUsage.getMax() * 100;
        }
        
        public String getFormattedUsedMemory() {
            return formatBytes(heapUsage.getUsed());
        }
        
        public String getFormattedMaxMemory() {
            return formatBytes(heapUsage.getMax());
        }
        
        public String getFormattedFreeMemory() {
            return formatBytes(getFreeMemory());
        }
        
        private String formatBytes(long bytes) {
            if (bytes < 1024) return bytes + " B";
            if (bytes < 1024 * 1024) return String.format("%.1f KB", bytes / 1024.0);
            if (bytes < 1024 * 1024 * 1024) return String.format("%.1f MB", bytes / (1024.0 * 1024.0));
            return String.format("%.1f GB", bytes / (1024.0 * 1024.0 * 1024.0));
        }
        
        @Override
        public String toString() {
            return String.format("堆内存: %s / %s (%.1f%%)", 
                    getFormattedUsedMemory(), getFormattedMaxMemory(), getHeapUsagePercentage());
        }
    }
    
    /**
     * 内存统计信息类
     */
    public static class MemoryStatistics {
        private final MemoryStatus status;
        private final long timestamp;
        
        public MemoryStatistics(MemoryStatus status) {
            this.status = status;
            this.timestamp = System.currentTimeMillis();
        }
        
        public MemoryStatus getStatus() { return status; }
        public long getTimestamp() { return timestamp; }
        
        public String getSummary() {
            return String.format("内存状态: %s, 时间: %s", 
                    status.toString(), new java.util.Date(timestamp));
        }
    }
}
